﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Quarto
{
    public class IA_dur
    {
        private int profondeur_max = 4;

        /*Calcule les coordonnées et la pièce à choisir par l'IA*/
        public Coup appel_min_max(Jeu jeu)
        {
            Coup meilleur_coup = new Coup();
            int max = -1000;
            /*Pour le premier coup, choisit des valeurs aléatoires*/
            if(jeu.Grille.test_grille_vide())
            {
                Coup coup_aleatoire = new Coup();
                Random alea = new Random();
                coup_aleatoire.X = alea.Next(0, 4);
                coup_aleatoire.Y = alea.Next(0, 4);
                int i = alea.Next(0, 16);
                while(jeu.Liste_piece.Liste_piece_depart[i].Couleur_piece == jeu.Piece_selectionnee.Couleur_piece
                    && jeu.Liste_piece.Liste_piece_depart[i].Forme_piece == jeu.Piece_selectionnee.Forme_piece
                    && jeu.Liste_piece.Liste_piece_depart[i].Trou_piece == jeu.Piece_selectionnee.Trou_piece
                    && jeu.Liste_piece.Liste_piece_depart[i].Taille_piece == jeu.Piece_selectionnee.Taille_piece)
                    i = alea.Next(0, 16);
                coup_aleatoire.Piece = jeu.Liste_piece.Liste_piece_depart[i];
                coup_aleatoire.Indice_piece_selectionnee = i;
                return coup_aleatoire;
            }
            /*Teste les différentes positions possibles*/
            for(int i = 0; i < 4; i++)
            {
                for(int j = 0; j < 4; j++)
                {
                    if(!jeu.Grille.Tab_case[i, j].Rempli)
                    {
                        Coup coup_a_jouer = new Coup(jeu.Piece_selectionnee, i, j, 0, jeu.Indice_piece_selectionnee);
                        /*Appel à la fonction récursive*/
                        coup_a_jouer = min_max(coup_a_jouer,-(jeu.Joueur_en_cours), jeu, 1);
                        /*Détermine la pièce dans Liste_piece_depart*/
                        for (int k = 0; k < 16; k++)
                        {
                            if (jeu.Liste_piece.Liste_piece_depart[k].Couleur_piece == coup_a_jouer.Piece.Couleur_piece
                                && jeu.Liste_piece.Liste_piece_depart[k].Forme_piece == coup_a_jouer.Piece.Forme_piece
                                && jeu.Liste_piece.Liste_piece_depart[k].Taille_piece == coup_a_jouer.Piece.Taille_piece
                                && jeu.Liste_piece.Liste_piece_depart[k].Trou_piece == coup_a_jouer.Piece.Trou_piece)
                                coup_a_jouer.Indice_piece_selectionnee = k;
                        }
                        if (coup_a_jouer.Valeur > max)
                        {
                            max = coup_a_jouer.Valeur;
                            meilleur_coup = new Coup(coup_a_jouer.Piece, i, j, coup_a_jouer.Valeur, coup_a_jouer.Indice_piece_selectionnee);
                        }
                    }
                }
            }
            return meilleur_coup;
        }

        /*Fonction récursive pour le calcul du minmax*/
        private Coup min_max(Coup coup_joue, int joueur_en_cours, Jeu jeu, int profondeur)
        {
            Coup meilleur_coup = new Coup();
            bool[] tab_piece_indisponible = new bool[16];
            for (int m = 0; m < 16; m++)
                if (!jeu.Liste_piece.Liste_piece_posee[m])
                    tab_piece_indisponible[m] = true;
            int min = 1000;
            int max = -1000;

            if (profondeur == profondeur_max)
            {
                coup_joue.Valeur = 25;
                return coup_joue;
            }
            
            coup_joue.appliquer_coup(jeu.Grille, jeu.Liste_piece);
            if(jeu.Grille.test_fin(jeu.Liste_motif_jeu))
            {
                coup_joue.annuler_coup(jeu.Grille, jeu.Liste_piece);
                coup_joue.Valeur = (-joueur_en_cours * 100) - (-joueur_en_cours * 10 *profondeur);
                return coup_joue;
            }
            else
            {
                /*Test des pièces non-jouées*/
                for (int k = 0; k < 16; k++)
                {
                    /*Test des cases où il n'y a pas de pièces*/
                    for (int i = 0; i < 4; i++)
                    {
                        for (int j = 0; j < 4; j++)
                        {
                            if (!jeu.Grille.Tab_case[i, j].Rempli)
                            {
                                if (!jeu.Liste_piece.Liste_piece_posee[k] && tab_piece_indisponible[k])
                                {
                                    Coup coup_simule = new Coup(jeu.Liste_piece.Liste_piece_depart[k], i, j, 0, k);
                                    coup_simule = min_max(coup_simule, -joueur_en_cours, jeu, profondeur + 1);

                                    if(coup_simule.Valeur < -joueur_en_cours)
                                    {
                                        tab_piece_indisponible[coup_simule.Indice_piece_selectionnee] = false;
                                    }

                                    if(joueur_en_cours == 1)
                                    {
                                        if (coup_simule.Valeur > max)
                                        {
                                            if ((max < 0) && (max != -1000))
                                                coup_simule.Valeur += 50;
                                            max = coup_simule.Valeur;
                                            meilleur_coup.X = i;
                                            meilleur_coup.Y = j;
                                            meilleur_coup.Indice_piece_selectionnee = k;
                                            meilleur_coup.Piece = jeu.Liste_piece.Liste_piece_depart[k];
                                            meilleur_coup.Valeur = coup_simule.Valeur;
                                        }
                                    }
                                    if(joueur_en_cours == -1)
                                    {
                                        if(coup_simule.Valeur < min)
                                        {
                                            min = coup_simule.Valeur;
                                            meilleur_coup.X = i;
                                            meilleur_coup.Y = j;
                                            meilleur_coup.Indice_piece_selectionnee = k;
                                            meilleur_coup.Piece = jeu.Liste_piece.Liste_piece_depart[k];
                                            meilleur_coup.Valeur = coup_simule.Valeur;
                                        }
                                    }

                                    if (!tab_piece_indisponible[meilleur_coup.Indice_piece_selectionnee])
                                    {
                                        max = -1000;
                                        min = 1000;
                                        i = 0;
                                        j = -1;
                                        k = 0;
                                    }
                                }
                            }
                        }
                    }
                }
                coup_joue.annuler_coup(jeu.Grille, jeu.Liste_piece);
                if(profondeur == 1)
                    return meilleur_coup;
                else
                {
                    coup_joue.Valeur = meilleur_coup.Valeur - 10 * profondeur;
                    return coup_joue;
                }
            }
        }
    }
}
